package com.nidu.demo.permission.ability;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.nidu.demo.common.enums.MenuTypeEnum;
import com.nidu.demo.common.enums.StatusEnum;
import com.nidu.demo.menu.gateway.MenuGateway;
import com.nidu.demo.menu.model.Menu;
import com.nidu.demo.menu.model.MenuCriteria;
import com.nidu.demo.role.gateway.RoleGateway;
import com.nidu.demo.role.gateway.RoleMenuGateway;
import com.nidu.demo.role.model.Role;
import com.nidu.demo.role.model.RoleMenu;
import com.nidu.demo.user.gateway.UserRoleGateway;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class PermissionDomainService {

    private final UserRoleGateway userRoleGateway;
    private final RoleMenuGateway roleMenuGateway;
    private final RoleGateway roleGateway;
    private final MenuGateway menuGateway;

    /** 是否超级管理员 */
    public boolean isSuperAdmin(List<Role> roles) {
        return roles.stream().anyMatch(Role::isSuperAdmin);
    }

    /** 获取用户有效角色（过滤禁用） */
    public List<Role> getActiveRoles(Long userId) {
        Set<Long> roleIds = userRoleGateway.getRoleIdsByUserId(userId);
        if (CollUtil.isEmpty(roleIds)) {
            return Collections.emptyList();
        }
        List<Role> roles = roleGateway.getByIds(roleIds);
        roles.removeIf(role -> StatusEnum.DISABLE.getValue().equals(role.getStatus()));
        return roles;
    }

    /** 获取用户可访问的菜单（过滤禁用） */
    public List<Menu> getActiveMenus(Long userId) {
        List<Role> roles = getActiveRoles(userId);
        if (CollUtil.isEmpty(roles)) {
            return Collections.emptyList();
        }
        if (isSuperAdmin(roles)) {
            return menuGateway.listByCondition(new MenuCriteria());
        }
        Map<Long, List<RoleMenu>> roleMenuMap =
                roleMenuGateway.getByRoleIds(roles.stream().map(Role::getId).collect(Collectors.toSet()));
        Set<Long> menuIds = roleMenuMap.values().stream()
                .flatMap(List::stream)
                .map(RoleMenu::getMenuId)
                .collect(Collectors.toSet());
        List<Menu> menus = menuGateway.getByIds(menuIds);
        menus.removeIf(menu -> StatusEnum.DISABLE.getValue().equals(menu.getStatus()));
        return menus;
    }

    /** 是否拥有任意权限 */
    public boolean hasAnyPermissions(Long userId, String[] permissions) {
        if (ArrayUtil.isEmpty(permissions)) {
            return true;
        }
        List<Menu> menus = getActiveMenus(userId);
        if (CollUtil.isEmpty(menus)) {
            return false;
        }
        return Arrays.stream(permissions).anyMatch(permission ->
                menus.stream().anyMatch(menu ->
                        permission.equals(menu.getPermission()) &&
                                MenuTypeEnum.BUTTON.getType().equals(menu.getMenuType())
                )
        );
    }

    /** 是否拥有任意角色 */
    public boolean hasAnyRoles(Long userId, String[] roles) {
        if (ArrayUtil.isEmpty(roles)) {
            return true;
        }
        List<Role> roleList = getActiveRoles(userId);
        if (CollUtil.isEmpty(roleList)) {
            return false;
        }
        if (isSuperAdmin(roleList)) {
            return true;
        }
        return Arrays.stream(roles).anyMatch(code ->
                roleList.stream().anyMatch(role -> code.equals(role.getRoleCode()))
        );
    }
}
